import { activeNodeId } from '@/components/business/BaseNode/state';
import { CACHE_GRAPH_DATA } from '@/constants/config';
import { useNodeResults } from '@/store/node-results';
import { registerEdge } from '@/utils/graph';
import storage from '@/utils/storage';
import { Graph, Platform } from '@antv/x6';
import { History } from '@antv/x6-plugin-history';
import { Snapline } from '@antv/x6-plugin-snapline';

export interface NodeStatus {
  id?: string;
  status?: 'DEFAULT' | 'PASS' | 'REJECT' | 'WAITING' | 'RUNNING';
  label?: string;
}
/** 画布交互状态： false禁用， true： 启用 */
const interactingState = ref(true);
const graph = ref<Graph | null>();

export const useGraph = (isInit = false) => {
  const container = ref<HTMLDivElement | null>(null);
  const flowId = new URLSearchParams(location.search).get('flowId') as string;
  const cacheKey = `${CACHE_GRAPH_DATA}-${flowId}`;
  const execResultsStore = useNodeResults();

  const saveGraph = () => {
    const data = graph.value!.toJSON();
    storage.remove(cacheKey);
    storage.set(cacheKey, data);
  };

  const setNodeDataById = (id: string, data: Record<string, any>) => {
    const node = graph.value?.getCellById(id);
    node?.setData(data);
  };

  const magnetAvailabilityHighlighter = {
    name: 'stroke',
    args: {
      padding: 4,
      attrs: {
        strokeWidth: 3,
        stroke: '#52c41a'
      }
    }
  };

  const resolveGraph = () => {
    return new Promise((resolve) => {
      if (graph.value) {
        resolve(graph.value);
      } else {
        setTimeout(() => {
          resolve(graph.value);
        }, 100);
      }
    });
  };

  const initGraph = () => {
    if (graph.value && graph.value.disposed) return;

    registerEdge();
    graph.value = new Graph({
      container: container.value as HTMLElement,
      // interacting() {
      //   return interactingState.value;
      // },
      interacting() {
        if (interactingState.value) {
          return true;
        } else {
          return {
            nodeMovable: true,
            magnetConnectable: false,
            edgeMovable: false,
            edgeLabelMovable: false,
            arrowheadMovable: false,
            vertexMovable: false,
            vertexAddable: false,
            vertexDeletable: false
          };
        }
      },
      panning: {
        enabled: true,
        eventTypes: ['leftMouseDown', 'mouseWheel']
      },
      mousewheel: {
        enabled: true,
        modifiers: 'ctrl',
        factor: 1.1,
        maxScale: 1.5,
        minScale: 0.5
      },
      highlighting: {
        magnetAvailable: magnetAvailabilityHighlighter,
        magnetAdsorbed: {
          name: 'stroke',
          args: {
            attrs: {
              fill: '#fff',
              stroke: '#31d0c6',
              strokeWidth: 4
            }
          }
        }
      },
      connecting: {
        snap: true,
        allowBlank: false,
        allowLoop: false,
        highlight: true,
        connectionPoint: 'anchor',
        anchor: 'center',
        validateMagnet({ magnet }) {
          return magnet.getAttribute('port-group') !== 'in';
        },
        validateConnection({ sourceMagnet, targetMagnet }) {
          // 只能从输出连接桩创建连接
          if (!sourceMagnet || sourceMagnet.getAttribute('port-group') === 'in') {
            return false;
          }

          // 只能连接到输入连接桩
          if (!targetMagnet || targetMagnet.getAttribute('port-group') !== 'in') {
            return false;
          }

          return true;
        },
        sourceAnchor: {
          name: 'left',
          args: {
            dx: Platform.IS_SAFARI ? 4 : 8
          }
        },
        targetAnchor: {
          name: 'right',
          args: {
            dx: Platform.IS_SAFARI ? 4 : -8
          }
        },
        createEdge(ev) {
          const { sourceCell } = ev;

          const edge = graph.value!.createEdge({
            shape: 'base-edge',
            connector: { name: 'smooth' },
            attrs: {
              line: {
                strokeDasharray: 5,
                strokeWidth: 1.1,
                targetMarker: 'classic',
                style: {
                  animation: 'ant-line 12s infinite linear'
                }
              }
            },
            defaultLabel: {
              markup: [
                {
                  tagName: 'rect',
                  selector: 'body'
                },
                {
                  tagName: 'text',
                  selector: 'label'
                }
              ],
              attrs: {
                text: {
                  fill: 'var(--color-blue-6)',
                  fontSize: 12,
                  textAnchor: 'middle',
                  textVerticalAnchor: 'middle'
                },
                rect: {
                  ref: 'label',
                  fill: 'var(--color-blue-1)',
                  stroke: 'var(--color-blue-4)',
                  refWidth: 14,
                  refHeight: 5,
                  refX: -7,
                  refY: -2.5,
                  rx: 20
                }
              },
              position: {
                distance: 0.5
              }
            },
            data: {
              source: sourceCell.id
            },
            zIndex: -1
          });

          if (sourceCell.shape === 'ConditionalNode') {
            const edges = graph.value?.getEdges() || [];
            const allPort = edges.map((item) => (item.getSource() as any).port) || [];
            const { length = 0 } = allPort.filter((p) => p === 'ConditionalNode_port_right');
            const nextEdgeName = length + 1;
            edge.appendLabel({
              attrs: {
                text: {
                  text: nextEdgeName
                }
              }
            });
          }
          return edge;
        }
      }
    });

    graph.value
      .use(
        // 历史记录插件
        new History({
          enabled: true,
          beforeAddCommand(_, args: any) {
            return args.key !== 'tools';
          }
        })
      )
      .use(
        // 对齐线插件
        new Snapline({
          enabled: true
        })
      );

    graph.value.on('cell:mouseenter', (ev) => {
      const { cell } = ev;

      if (execResultsStore.hasExecResult) return;

      const deleteHandle = () => {
        cell.remove();
        saveGraph();
      };

      if (cell.isNode() && interactingState.value) {
        cell.addTools({
          name: 'button-remove',
          args: {
            x: '100%',
            y: 0,
            offset: { x: -2, y: 2 },
            onClick: deleteHandle
          }
        });
      } else if(interactingState.value){
        cell.addTools({
          name: 'button-remove',
          args: {
            distance: 0.8,
            markup: [
              {
                tagName: 'circle',
                selector: 'circle',
                attrs: {
                  r: 10,
                  fill: 'var(--color-red-4',
                  stroke: 'var(--color-red-4',
                  strokeWidth: 2,
                  cursor: 'pointer'
                }
              }
            ],
            onClick: deleteHandle
          }
        });
      }
    });

    graph.value.on('cell:mouseleave', ({ cell }) => {
      cell.removeTools();
    });

    graph.value.on('edge:connected', ({ edge }) => {
      edge.attr({
        line: {
          strokeDasharray: ''
        }
      });
    });

    graph.value.on('edge:click', (ev) => {
      // ev.edge.setLabels([
      //   {
      //     attrs: {
      //       text: {
      //         text: '1'
      //       }
      //     }
      //   }
      // ]);
      // ev.cell.setData({
      //   test: 1
      // });
      activeNodeId.value = ev.edge.id;
    });

    graph.value.on('node:change:data', ({ node }) => {
      const edges = graph.value!.getIncomingEdges(node);
      const { status } = node.getData() as NodeStatus;
      edges?.forEach((edge) => {
        if (status === 'RUNNING') {
          edge.attr('line/strokeDasharray', 5);
          edge.attr('line/style/animation', 'running-line 30s infinite linear');
        } else {
          edge.attr('line/strokeDasharray', '');
          edge.attr('line/style/animation', '');
        }
      });
    });

    const cacheGraphData = storage.get(cacheKey);
    if (cacheGraphData) {
      graph.value.fromJSON(cacheGraphData);
    }
    // 缓存画布数据
    graph.value.on('cell:change:*', () => {
      saveGraph();
    });
  };

  const updateInteractingState = (state: boolean) => {
    interactingState.value = state;
  };

  if (isInit === true) {
    onMounted(initGraph);

    onUnmounted(() => {
      graph.value?.dispose();
      graph.value = null;
    });
  }

  return {
    graph,
    updateInteractingState,
    interactingState,
    setNodeDataById,
    resolveGraph,
    saveGraph,
    container
  };
};
